/*
 * \brief   Timed event scheduler interface
 * \date    2005-10-24
 * \author  Norman Feske
 */

/*
 * Copyright (C) 2005-2009 Norman Feske
 * Genode Labs, Feske & Helmuth Systementwicklung GbR
 *
 * This file is part of the Genode OS framework, which is distributed
 * under the terms of the GNU General Public License version 2.
 */

#ifndef _INCLUDE__BASE__ALARM_H_
#define _INCLUDE__BASE__ALARM_H_

#include <base/lock.h>

namespace Genode {

	class Alarm_scheduler;

	class Alarm
	{
		public:

			typedef unsigned long Time;

		private:

			friend class Alarm_scheduler;

			Time             _deadline;       /* next deadline                */
			Time             _period;         /* duration between alarms      */
			int              _active;         /* set to one when active       */
			Alarm           *_next;           /* next alarm in alarm list     */
			Alarm_scheduler *_scheduler;      /* currently assigned scheduler */
			Lock             _dispatch_lock;  /* taken during handle function */

			void _assign(Time period, Time deadline, Alarm_scheduler *scheduler) {
				_period = period, _deadline = deadline, _scheduler = scheduler; }

			void _reset() {
				_assign(0, 0, 0), _active = 0, _next = 0; }

		protected:

			/**
			 * Function to be called on when deadline is reached
			 *
			 * This function must be implemented by a derived class.  If the
			 * return value is 'true' and the alarm is periodically scheduled,
			 * the alarm is scheduled again.
			 */
			virtual bool on_alarm() { return false; }

		public:

			Alarm() { _reset(); }

			virtual ~Alarm();
	};


	class Alarm_scheduler
	{
		private:

			Alarm       *_head;   /* head of alarm list                       */
			Alarm::Time  _now;    /* recent time (updated by handle function) */
			Lock         _lock;   /* protect alarm list                       */

			friend class Alarm;

			/**
			 * Enqueue alarm into alarm queue
			 *
			 * This is a helper function for 'schedule' and 'handle'.
			 */
			void _unsynchronized_enqueue(Alarm *alarm);

			/**
			 * Dequeue alarm from alarm queue
			 */
			void _unsynchronized_dequeue(Alarm *alarm);

			/**
			 * Dequeue next pending alarm from alarm list
			 *
			 * \return  dequeued pending alarm
			 * \retval  0  no alarm pending
			 */
			Alarm *_get_pending_alarm();

		public:

			Alarm_scheduler() : _head(0), _now(0) { }
			~Alarm_scheduler(); 

			/**
			 * Schedule absolute timeout
			 *
			 * \param timeout  absolute point in time for execution
			 */
			void schedule_absolute(Alarm *alarm, Alarm::Time timeout);

			/**
			 * Schedule alarm (periodic timeout)
			 *
			 * \param period  alarm period
			 *
			 * The first deadline is overdue after this call, i.e. on_alarm() is
			 * called immediately.
			 */
			void schedule(Alarm *alarm, Alarm::Time period);

			/**
			 * Remove alarm from schedule
			 */
			void discard(Alarm *alarm);

			/**
			 * Handle alarms
			 *
			 * \param now  current time
			 */
			void handle(Alarm::Time now);
	};

}

#endif /* _INCLUDE__BASE__ALARM_H_ */
